/*
 * main.cpp - Grupo 5 - Prog. Avanzada 2011
 *
 *  Javier Dominguez - 4.901.161-6
 *  Marcelo Parada - 1.977.094-9
 *  Rodrigo Ruiz - 4.481.611-2
 *  Maximiliano Silvera - 4.106.938-6
 */
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <iomanip>
#include "dt/UsuarioDT.h"
#include "logica/IRegistroUsuario.h"
#include "util/ControllerFactory.h"
#include "dt/SingleDT.h"
#include "dt/SolistaDT.h"
#include "dt/BandaDT.h"
#include <exception>
#include "dt/ArtistaDT.h"
#include "dt/AlbumDT.h"
#include "dt/ReproduccionDT.h"

static const int CU_REGISTRO_USUARIO = 1;
static const int CU_COMPARTIR_TEMA_SINGLE = 2;
static const int CU_COMPARTIR_PISTA_ALBUM = 3;
static const int CU_CONSULTAR_INFO_TEMA = 4;
static const int CU_ELIMINAR_TEMA = 5;
static const int CU_ETIQUETAR = 6;
static const int CU_REPRODUCIR_TEMA = 7;
static const int CU_GLOBAL = 8;
static const int CONTINUAR = 0;
static const int SALIR = -1;

static const int CU_GLOBAL_LISTADO_USUARIOS = 1;
static const int CU_GLOBAL_LISTADO_TEMAS = 2;
static const int CU_GLOBAL_LISTADO_SINGLES = 3;
static const int CU_GLOBAL_LISTADO_PISTAS = 4;
static const int CU_GLOBAL_LISTADO_ALBUMS = 5;
static const int CU_GLOBAL_LISTADO_ARTISTAS = 6;
static const int CU_GLOBAL_LISTADO_SOLISTAS = 7;
static const int CU_GLOBAL_LISTADO_BANDAS = 8;
static const int CU_GLOBAL_LISTADO_ETIQUETAS = 9;
static const int CU_GLOBAL_LISTADO_REPRODUCCIONES = 10;
static const int CU_GLOBAL_JUEGO_DATOS = 11;
static const int CU_GLOBAL_SETEAR_FECHA_SISTEMA = 12;

int leerEntero();
void cabecera();
void menuPrincipal();
int iniciarCU(int opcion);
int salir();

// CU Solicitados
int registroUsuario();
int compartirTemaSingle();
int compartirPistaAlbum();
int consultarInfoTema();
int eliminarTema();
int etiquetar();
int reproducirTema();
int ingresarDatosPrueba();
int salir();

// CU Global
int global();
void submenuGlobal();
int iniciarGlobal(int opcion);

// CU Global
int mostrarListadoUsuarios();
int mostrarListadoTemas();
int mostrarListadoSingles();
int mostrarListadoPistas();
int mostrarListadoAlbums();
int mostrarListadoArtistas();
int mostrarListadoSolistas();
int mostrarListadoBandas();
int mostrarListadoEtiquetas();
int mostrarListadoReproducciones();
int ingresarInfoInicial();
int setFechaSys();

using namespace std;

int main()
{
	int opcion;

	while(true)
	{
		menuPrincipal();

		opcion = leerEntero();

		/*
		 * Se invoca el metodo que corresponda a la opcion seleccionada,
		 * si este retorna 0 entonces se cierra la aplicacion.
		 */
		if(iniciarCU(opcion) == SALIR)
		{
			return SALIR;
		}
	}
}

/*
 * Imprie la cabecera de la pantalla
 */
void cabecera()
{
	system("clear");

	cout << "------------------------------------------------------------------------- " << endl;
	cout << "|         .:: Prog. Avanzada 2011 - Grupo 5 - Tarea 7 ::.               | " << endl;
	cout << "------------------------------------------------------------------------- " << endl;

	cout << "Fecha Sistema: "<< ControllerFactory::getInstance()->getGlobalController()->getFechaSys()->toString() << endl << endl;
}

/*
 * Dibuja el menu principal
 */
void menuPrincipal()
{
	cabecera();

	cout << "1. Registrar de Usuario." << endl;
	cout << "2. Compartir Tema Single." << endl;
	cout << "3. Compartir Pista Album." << endl;
	cout << "4. Consultar Información Tema." << endl;
	cout << "5. Eliminar Tema." << endl;
	cout << "6. Etiquetar." << endl;
	cout << "7. Reproducir Tema." << endl;
	cout << "8. Utilidades." << endl;
	cout << "0. Salir." << endl << endl;

	cout << "Indique la opcion deseada: ";
}

void submenuGlobal()
{
	cabecera();

	cout << " 1. Listado de Usuarios. \n";
	cout << " 2. Listado de Temas. \n";
	cout << " 3. Listado de Singles. \n";
	cout << " 4. Listado de Pistas. \n";
	cout << " 5. Listado de Albums. \n";
	cout << " 6. Listado de Artistas. \n";
	cout << " 7. Listado de Solistas. \n";
	cout << " 8. Listado de Bandas. \n";
	cout << " 9. Listado de Etiquetas. \n";
	cout << "10. Listado de Reproducciones. \n";
	cout << "11. Ingresar Juego de Datos. \n";
	cout << "12. Setear Fecha del Sistema. \n";
	cout << " 0. Salir. \n\n";

	cout << "Indique la opcion deseada: ";
}

int leerEntero()
{
	int ret;

	string sIn;

	cin >> sIn;

	if(isdigit(sIn[0]) == 0) // Si no es un numero
	{
		cout << "Numero incorrecto, reintente:";

		return leerEntero();
	}
	else
	{
		ret = atoi(sIn.data());

		if(ret < 0)
		{
			cout << "ERROR: No se permite negativo.";

			return leerEntero();
		}
	}

	return ret;
}

/*
 * Metodo utilizado por los CU compartir tema single y compartir pista album para obtener los artistas a relacionar
 */
ColConcrete<ArtistaDT*> *solicitarArtistas(string msjSolicitud, ICompartirTemaSingle *cCompTemaSingle, ICompartirPistaAlbum *cCompPistaAlbum)
{
	ColConcrete<ArtistaDT*> *colArtistas = new ColConcrete<ArtistaDT*>();

	cout << endl << msjSolicitud << endl;

	ArtistaDT *artistaDTAux;

	string nombreArtista;

	int integrantesArtista;

	int tipoArtista;

	int opcion;

	do
	{
		cout << endl << "Nombre artista: "; cin >> nombreArtista;

		if(cCompTemaSingle != NULL)
		{
			artistaDTAux = cCompTemaSingle->obtenerArtista(nombreArtista);
		}
		else if(cCompPistaAlbum != NULL)
		{
			artistaDTAux = cCompPistaAlbum->obtenerArtista(nombreArtista);
		}

		// Si no existe el artista
		if(artistaDTAux == NULL)
		{
			cout << endl << "El artista no existe, debe completar todos los datos." << endl;

			cout << endl << "Indique el tipo de artista. [1: Solista, 2: Banda].";

			tipoArtista = leerEntero();

			if(tipoArtista == 1)
			{
				artistaDTAux = new SolistaDT(nombreArtista);
			}
			else if(tipoArtista == 2)
			{
				cout << endl << "Cantidad integrantes: ";

				integrantesArtista = leerEntero();

				artistaDTAux = new BandaDT(nombreArtista, integrantesArtista);
			}
		}

		colArtistas->add(artistaDTAux);

		try
		{
			if(cCompTemaSingle != NULL)
			{
				cCompTemaSingle->crearArtista(artistaDTAux);
			}
			else if(cCompPistaAlbum != NULL)
			{
				cCompPistaAlbum->crearArtista(artistaDTAux);
			}
		}
		catch(string e)
		{
			// Nothing
		}

		cout << endl << "Desea agregar otro artista?. [1: SI || 0: No]:";

		opcion = leerEntero();
	}
	while(opcion == 1);

	return colArtistas;
}

/*
 * Inicia el Caso de uso correspondiente de acuerdo a la opcion
 * ingresada por el usuario
 */
int iniciarCU(int opcion)
{
	cabecera();

	if(opcion == 0)
	{
		return salir();
	}
	else if(opcion == CU_REGISTRO_USUARIO)
	{
		return registroUsuario();
	}
	else if(opcion == CU_COMPARTIR_TEMA_SINGLE)
	{
		return compartirTemaSingle();
	}
	else if(opcion == CU_COMPARTIR_PISTA_ALBUM)
	{
		return compartirPistaAlbum();
	}
	else if(opcion == CU_CONSULTAR_INFO_TEMA)
	{
		return consultarInfoTema();
	}
	else if(opcion == CU_ELIMINAR_TEMA)
	{
		return eliminarTema();
	}
	else if(opcion == CU_ETIQUETAR)
	{
		return etiquetar();
	}
	else if(opcion == CU_REPRODUCIR_TEMA)
	{
		return reproducirTema();
	}
	else if(opcion == CU_GLOBAL)
	{
		return global();
	}

	return CONTINUAR;
}

/*
 * Inicia el Caso de uso utilidades de acuerdo a la opcion
 * ingresada por el usuario
 */

int iniciarGlobal(int opcion)
{
	cabecera();

	if(opcion == 0)
	{
		return SALIR;
	}
	else if(opcion == CU_GLOBAL_LISTADO_USUARIOS)
	{
		return mostrarListadoUsuarios();
	}
	else if(opcion == CU_GLOBAL_LISTADO_TEMAS)
	{
		return mostrarListadoTemas();
	}
	else if(opcion == CU_GLOBAL_LISTADO_SINGLES)
	{
		return mostrarListadoSingles();
	}
	else if(opcion == CU_GLOBAL_LISTADO_PISTAS)
	{
		return mostrarListadoPistas();
	}
	else if(opcion == CU_GLOBAL_LISTADO_ALBUMS)
	{
		return mostrarListadoAlbums();
	}
	else if(opcion == CU_GLOBAL_LISTADO_ARTISTAS)
	{
		return mostrarListadoArtistas();
	}
	else if(opcion == CU_GLOBAL_LISTADO_SOLISTAS)
	{
		return mostrarListadoSolistas();
	}
	else if(opcion == CU_GLOBAL_LISTADO_BANDAS)
	{
		return mostrarListadoBandas();
	}
	else if(opcion == CU_GLOBAL_LISTADO_ETIQUETAS)
	{
		return mostrarListadoEtiquetas();
	}
	else if(opcion == CU_GLOBAL_LISTADO_REPRODUCCIONES)
		{
			return mostrarListadoReproducciones();
		}
		else if (opcion == CU_GLOBAL_SETEAR_FECHA_SISTEMA)
	{
		return setFechaSys();
	}
	else if(opcion == CU_GLOBAL_JUEGO_DATOS)
	{
		return ingresarDatosPrueba();
	}
	return CONTINUAR;
}

int global()
{
	{
		int opcion;

		while(true)
		{
			submenuGlobal();

			opcion = leerEntero();

			/*
			 * Se invoca el metodo que corresponda a la opcion seleccionada,
			 * si este retorna 0 entonces se cierra la aplicacion.
			 */
			if(iniciarGlobal(opcion) == SALIR)
			{
				return CONTINUAR;
			}
		}
	}
}



int salir()
{
	cout << "Gracias por todo, presione una tecla para salir.";

	getchar();

	getchar();

	system("clear");

	return SALIR;
}

/*
 * CU - Registro de Usuario
 *
 * El caso de uso comienza cuando el Usuario desea crearse en la red.
 * Para ello debe ingresar su nombre completo, mail y el nick que lo identificara en la red.
 * Si el nick ingresado esta disponible, el Sistema registra el nuevo usuario en la red,
 * de lo contrario el Usuario cambia el nick hasta que esta disponible o decida cancelar el registro.
 */
int registroUsuario()
{
	IRegistroUsuario *controller = ControllerFactory::getInstance()->getRegistroUsuarioController();

	/*
	 * Solicito los datos del usuario
	 */
	string nick;

	string nombre;

	string mail;

	cout << "Ingrese los datos del usuario." << endl << endl;

	cout << "Nombre: "; cin >> nombre;

	cout << "E-mail: "; cin >> mail;

	/*
	 * Chequeo si nick esta disponible
	 */
	bool nickDisponible = false;

	int opcion;

	while(!nickDisponible)
	{
		cout << "Nick: ";

		cin >> nick;

		nickDisponible = controller->nickDisponible(nick);

		// Si nick no disponible solicito nuevamente el nick o permito cancelar y vuelve al menu
		if(!nickDisponible)
		{
			cout << endl << "Nick no disponible. [1: Reintentar || 0: Salir]:";

			opcion = leerEntero();

			cout << endl;

			if(opcion != 1)
			{
				return CONTINUAR;
			}
		}
	}

	/*
	 * Ingreso la informacion al sistema
	 */
	UsuarioDT *usuarioDT = new UsuarioDT(nick, nombre, mail);

	controller->crearUsuario(usuarioDT);

	cout << endl << "Usuario registrado correctamente.\n\n";

	getchar();

	getchar();

	// Limpio la memoria
	delete usuarioDT;

	return CONTINUAR;
}

/*
 * CU - Compartir Tema Single
 *
 * El caso de uso comienza cuando el Usuario desea compartir un nuevo single,
 * ingresando el titulo, duracion y año del mismo. Luego ingresa uno a uno los
 * artistas que interpretan el single (al menos uno). En caso de existir el artista
 * en la red ingresa su nombre, mientras que si es nuevo indica su nombre, si es
 * solista o banda y la cantidad de integrantes (si es banda). Para finalizar, el
 * Sistema da de alta el nuevo tema single asi como los nuevos artistas y devuelve un
 * id generado para identificar al tema en el Sistema.
 */
int compartirTemaSingle()
{
	int ret = CONTINUAR;

	ICompartirTemaSingle *controller = ControllerFactory::getInstance()->getCompartirTemaSingleController();

	/*
	 * Solicito informacion de single
	 */
	string tituloSingle;

	int minutosSingle;

	int segundosSingle;

	int anioSingle;

	cout << "Ingrese los datos del Single." << endl << endl;

	cout << "Titulo: "; cin >> tituloSingle;

	cout << "Minutos (dur.): "; minutosSingle = leerEntero();

	cout << "Segundos (dur.): "; segundosSingle = leerEntero();

	cout << "Año: "; anioSingle = leerEntero();

	SingleDT *singleDT = new SingleDT(anioSingle, tituloSingle, new Tiempo(minutosSingle, segundosSingle));

	/*
	 * Solicito los artistas del single
	 */
	ColConcrete<ArtistaDT*> *colArtistasSingle = solicitarArtistas("Ingrese los artistas del single.", controller, NULL);

	/*
	 * Ingreso la informacion al sitema
	 */
	try
	{
		singleDT->setId(controller->crearSingle(singleDT));

		ConcreteIterator<ArtistaDT*> *iterArtistasSingle = colArtistasSingle->getIterator();

		ArtistaDT *currArtistaDT;

		while(iterArtistasSingle->hasCurrent())
		{
			currArtistaDT = iterArtistasSingle->current();

			try
			{
				controller->asociarArtistaTema(currArtistaDT, singleDT);
			}
			catch(string e2)
			{
				cout << endl << "INFO:" << e2 << endl;
			}


			iterArtistasSingle->next();
		}

		cout << endl << "Single compartido correctamente.(Id: " << singleDT->getId() << ").\n\n";

	}
	catch(string e1)
	{
		cout << endl << "ERROR:" << e1 << endl << endl;

		ret = SALIR;
	}

	getchar();

	getchar();

	/*
	 * Limpio la memoria
	 */
	delete singleDT;

	delete colArtistasSingle; // Este elimina el contenido del iterArtistas y de artistaDT

	return ret;
}

/*
 * CU - Compartir Pista Album
 *
 * El caso de uso comienza cuando el Usuario desea compartir una nueva pista de album,
 * ingresando el titulo, duracion y numero de pista. Luego ingresa uno a uno los artistas
 * que interpretan la pista (al menos uno). En caso de existir el artista en la red
 * ingresa su nombre, mientras que si es nuevo indica su nombre, si es solista o banda
 * y la cantidad de integrantes (si es banda). Una vez ingresados los artistas, el Sistema
 * lista los albumes registrados en la red. El Usuario selecciona uno de ellos o en caso de
 * no estar en el listado lo da de alta ingresando su nombre, anio de edicion y artistas que
 * lo interpretan (de igual forma que para artistas de la pista). Para finalizar, el Sistema
 * de alta la nueva pista de album, los nuevos artistas, el album (si aplica) y devuelve un id
 * generado para identificar al tema en el Sistema.
 */
int compartirPistaAlbum()
{
	int ret = CONTINUAR;

	ICompartirPistaAlbum *controller = ControllerFactory::getInstance()->getCompartirPistaAlbumController();

	/*
	 * Solicito informacion de pista
	 */
	string tituloPista;

	int numeroPista;

	int minutosPista;

	int segundosPista;

	cout << "Ingrese los datos de la Pista." << endl << endl ;

	cout << "Titulo: "; cin >> tituloPista;

	cout << "Minutos (dur.): "; minutosPista = leerEntero();

	cout << "Segundos (dur.): "; segundosPista = leerEntero();

	cout << "Numero de Pista: "; numeroPista = leerEntero();

	PistaDT *pistaDT = new PistaDT(numeroPista, tituloPista, new Tiempo(minutosPista, segundosPista));

	/*
	 * Solicito los artistas de la pista
	 */
	ColConcrete<ArtistaDT*> *colArtistasPista = solicitarArtistas("Ingrese los artisas de la pista.", NULL, controller);

	/*
	 * Solicitar album de la pista
	 */
	AlbumDT *albumDT = NULL;

	int opcion;

	string nombreAlbum;

	int anioEdicionAlbum;

	cout << endl << "Albumes registrados." << endl << endl << controller->obtenerListadoAlbumes()->toString() ;

	cout << endl << "Seleccionar album. [1: De la lista || 0: Ingrese nuevo album]: "; opcion = leerEntero();

	cout << endl << "Ingrese nombre del Album: "; cin >> nombreAlbum;

	if(opcion == 0)
	{
		cout << endl << "Ingrese año de edicion: "; anioEdicionAlbum = leerEntero();

		albumDT = new AlbumDT(nombreAlbum, anioEdicionAlbum);
	}

	while(albumDT == NULL)
	{
		albumDT = controller->obtenerAlbum(nombreAlbum);

		if(albumDT == NULL)
		{
			cout << endl << "El album no existe. [1: Reintentar || 0: Salir]:"; cin >> opcion;

			if(opcion != 1)
			{
				return SALIR;
			}

			cout << endl << "Ingrese nombre album: "; cin >> nombreAlbum;
		}
	}

	/*
	 * Solicito los artistas del album
	 */
	ColConcrete<ArtistaDT*> *colArtistasAlbum = solicitarArtistas("Ingrese los artistas del album.", NULL, controller);

	/*
	 * Ingreso la informacion a el sistema
	 */
	try
	{
		try
		{
			pistaDT->setId(controller->crearPista(pistaDT));
		}
		catch(string e2)
		{
			cout <<  "INFO:" << e2 << endl;
		}

		try
		{
			controller->crearAlbum(albumDT);
		}
		catch(string e2)
		{
			cout <<  "INFO:" << e2 << endl;
		}

		controller->asociarAlbumPista(albumDT, pistaDT); // Asocio el album a la pista

		ArtistaDT *currArtistaDT;

		// Asocio los artistas a la pista
		ConcreteIterator<ArtistaDT*> *iterArtistasPista = colArtistasPista->getIterator();

		while(iterArtistasPista->hasCurrent())
		{
			currArtistaDT = iterArtistasPista->current();

			try
			{
				controller->asociarArtistaTema(currArtistaDT, pistaDT);
			}
			catch(string e2)
			{
				cout << "INFO:" << e2 << endl;
			}

			iterArtistasPista->next();
		}

		// Asocio los artistas al album
		ConcreteIterator<ArtistaDT*> *iterArtistasAlbum = colArtistasAlbum->getIterator();

		while(iterArtistasAlbum->hasCurrent())
		{
			currArtistaDT = iterArtistasAlbum->current();

			try
			{
				controller->asociarArtistaAlbum(currArtistaDT, albumDT);
			}
			catch(string e2)
			{
				cout << "INFO:" << e2 << endl;
			}

			iterArtistasAlbum->next();
		}

		cout << endl << "Pista compartida correctamente. (Id: " << pistaDT->getId() << ").\n\n";
	}
	catch(string e1)
	{
		cout << "ERROR:" << e1 << endl;

		ret = SALIR;
	}

	getchar();

	getchar();

	// Limpio la memoria

	delete pistaDT;

	delete albumDT;

	delete colArtistasPista;

	delete colArtistasAlbum;

	return CONTINUAR;
}

/*
 * CU - Consultar Informacion de Tema
 *
 * El caso de uso comienza cuando el Usuario quiere obtener la informacion de un tema. Para ello
 * ingresa el id de un tema a consultar y el Sistema muestra toda la informacion del tema
 * incluyendo los datos de sus artistas, album (si aplica), cantidad de reproducciones totales
 * y fecha de ultima reproduccion
 */
int consultarInfoTema()
{
	IConsultarInformacionTema *controller = ControllerFactory::getInstance()->getConsultarInformacionTemaController();
	/*
	 * Solicito el tema a escuchar
	 */
	int idTema;

	cout << "Ingrese el Id del Tema: "; idTema = leerEntero();

	TemaDT *temaDT = controller->obtenerInfoTema(idTema);

	ColConcrete<ReproduccionDT*> *reproduccionesTema = controller->obtenerReproduccionesTema(idTema);

	// Imprimo la info basica del tema, aqui si se imprime una pista se muestra la info del album
	cout << endl <<  "Informacion basica del tema." << endl << endl;

	// Cabecera tema
	cout << left;
	cout << setw(6) << "Id";
	cout << setw(25) << "Titulo";
	cout << setw(10) << "Duracion";
	cout << setw(8) << "Anio";
	cout << setw(20) << "Album";
	cout << setw(6) << "Track";
	cout << endl << endl;

	cout << temaDT->toString() << endl << endl << endl;

	cout << "Artistas del tema." << endl << endl;

	cout << temaDT->getArtistas()->toString() << endl;

	int cantidadRep = 0;

	Fecha *fechaMaxima = new Fecha(1,1,1,0,0);

	ConcreteIterator<ReproduccionDT*> *iterRep = reproduccionesTema->getIterator();

	while(iterRep->hasCurrent())
	{
		cantidadRep += iterRep->current()->getCantidad();

		if(fechaMaxima->menorA(iterRep->current()->getFechaUltima()))
		{
			fechaMaxima->setAnio(2010);
			fechaMaxima->setAnio(iterRep->current()->getFechaUltima()->getAnio());
			fechaMaxima->setMes(iterRep->current()->getFechaUltima()->getMes());
			fechaMaxima->setDia(iterRep->current()->getFechaUltima()->getDia());
			fechaMaxima->setHora(iterRep->current()->getFechaUltima()->getHora());
			fechaMaxima->setMinuto(iterRep->current()->getFechaUltima()->getMinuto());
		}

		iterRep->next();
	}

    if ( cantidadRep != 0)
	{
    	cout << "Reproducciones totales: " << cantidadRep << endl << endl;
    	cout << "Ultima reproduccion: " << fechaMaxima->toString() << endl << endl;
	}

	getchar();

	getchar();

	delete temaDT;

	delete reproduccionesTema;

	return CONTINUAR;
}

/*
 * CU - Eliminar Tema
 *
 * El caso de8 uso comienza cuando el Usuario desea quitar un tema de la red. Para ello el
 * Sistema muestra una lista de temas compartidos en la red. El Usuario selecciona de esa
 * lista el id del tema a eliminar y el Sistema lo elimina solo en caso de que no haya sido
 * escuchado por ningun usuario de la red, de lo contrario se genera un error y no se elimina el tema.
 */
int eliminarTema()
{
	IEliminarTema *controller = ControllerFactory::getInstance()->getEliminarTemaController();

	int ret = CONTINUAR;

	// Muestro el listado de los temas en la red
	ColConcrete<TemaDT*> *listaTemas = controller->obtenerListadoTemas();

	// Cabecera tema
	cout << left;
	cout << setw(6) << "Id";
	cout << setw(25) << "Titulo";
	cout << setw(10) << "Duracion";
	cout << setw(8) << "Anio";
	cout << setw(20) << "Album";
	cout << setw(6) << "Track";
	cout << endl << endl;

	// Listado de temas
	cout << listaTemas->toString();

	try
	{
		int idTema;

		cout << "Indique el id del tema a eliminar: "; idTema = leerEntero();

		controller->eliminarTema(idTema);

		cout << endl << "Tema eliminado correctamente." << endl << endl;
	}
	catch(string e)
	{
		cout << "ERROR: " << e.data();
	}

	getchar();

	getchar();

	delete listaTemas;

	return ret;
}

/*
 * CU - Etiquetar
 *
 * El caso de uso comienza cuando el Usuario desea etiquetar un album o artista registrado.
 * Para ello indica el elemento a etiquetar (album o artista) y el Sistema muestra la
 * informacion completa de los elementos disponibles en la red de acuerdo a la opcian
 * ingresada. Luego el Usuario selecciona el elemento a etiquetar de la lista correspondiente
 * y el Sistema muestra sus etiquetas y lista ademas las disponibles en la red. El Usuario
 * agrega una a una las etiquetas (al menos una) y en caso de querer utilizar etiquetas no
 * registradas, ingresa el nombre de cada nueva etiqueta. Para finalizar, el Sistema muestra
 * la informacion del elemento a etiquetar y sus nuevas etiquetas, debiendo el Usuario confirmar
 * o cancelar dicho etiquetado. En caso de confirmar, el Sistema efectua el etiquetado y da de
 * alta las nuevas etiquetas.
 */
int etiquetar()
{
	IEtiquetarElemento *controller = ControllerFactory::getInstance()->getEtiquetarElementoController();

	// Indica el elemento y muestra el listado
	int opcion;

	cout << "Que desea Etiquetar?. [1: Album || 2: Artista]:"; opcion = leerEntero();

	if(opcion == 1)
	{
		cout << endl << "Albumes del Sistema :" << endl << controller->obtenerListadoAlbumes()->toString();
	}
	else if(opcion == 2)
	{
		cout << endl << "Artistas del Sistema :" << endl << controller->obtenerListadoArtistas()->toString();
	}
	else
	{
		return SALIR;
	}

	// Selecciona de la lista
	string nombreElemento;

	cout << "Indique el elemento a etiquetar: "; cin >> nombreElemento;

	ElementoDT *elementoDT = NULL;

	if(opcion == 1)
	{
		elementoDT = controller->obtenerAlbum(nombreElemento);
	}
	else if(opcion == 2)
	{
		elementoDT = controller->obtenerArtista(nombreElemento);
	}

	// Mostrar etiquetas del elemento
	ColConcrete<EtiquetaDT*> *etiquetasElemento = controller->listarEtiquetasElementoYDisponibles(nombreElemento);

	cout << endl << "Etiquetas del elemento: " << endl << etiquetasElemento->toString() << endl;

	// Agrego las etiquetas
	ColConcrete<EtiquetaDT*> *etiquetasAgregar = new ColConcrete<EtiquetaDT*>();

	string nombreEtiqueta;

	int agregarOtra = -1;

	cout << "Agregue las etiquetas." << endl;

	do
	{
		cout << "Existente o nueva: [1: Existente || 2: Nueva].";

		opcion = leerEntero();

		cout << "Nombre de etiqueta: ";  cin >> nombreEtiqueta;

		if(opcion == 2)
		{
			controller->crearEtiqueta(new EtiquetaDT(nombreEtiqueta));
		}

		etiquetasAgregar->add(controller->obtenerEtiqueta(nombreEtiqueta));

		cout << "Agregar otra. [1: SI || 0: NO]";

		agregarOtra = leerEntero();
	}
	while(agregarOtra == 1);

	// Muestro la informacion a etiquetar
	cout << "Elemento a etiquetar:" << endl;

	cout << elementoDT->toString() << endl;

	cout << "Etiquetas a asociar:" << endl;

	cout << etiquetasAgregar->toString();

	cout << "Confirme etiquetado. [1: Confirmar || 0: Salir].";

	opcion = leerEntero();

	if(opcion == 1)
	{
		// Ingreso la info al sistema
		ConcreteIterator<EtiquetaDT*> *iterEtiquetas = etiquetasAgregar->getIterator();

		while(iterEtiquetas->hasCurrent())
		{
			controller->asociarElementoEtiqueta(elementoDT, iterEtiquetas->current());

			iterEtiquetas->next();
		}
	}

	getchar();

	getchar();

	// Limpio la memoria
	delete elementoDT;

	delete etiquetasElemento;

	delete etiquetasAgregar;

	return CONTINUAR;
}

/*
 * CU - Reproducir Tema
 *
 * El caso de uso comienza cuando el Usuario desea escuchar un tema. Para ello puede hacerlo
 * indicando directamente su nick y el id del tema a escuchar o bien buscando por etiquetas.
 * En este ultimo caso el Sistema muestra un listado de etiquetas registradas, de las cuales
 * el Usuario selecciona una. A partir de esta seleccion el Sistema muestra los temas de los
 * artistas o albumes que contengan esa etiqueta. Para finalizar el Usuario ingresa el id de
 * un tema del listado (y su nick) y el Sistema registra la reproduccion del tema.
 */
int reproducirTema()
{

	cout << "INFO: CU en desarrollo." << endl << endl;

	getchar();

	getchar();

	return CONTINUAR;
}

int setFechaSys()
{
	IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();
	/*
	 * Solicito los datos del usuario
	 */
	int dia;

	int mes;

	int anio;

	int hora;

	int minuto;

	int opcion;

	cout << "\n\nIngrese fecha del sistema.\n\n";

	cout << "Dia: "; dia = leerEntero();

	cout << "Mes: "; mes = leerEntero();

	cout << "Año: "; anio = leerEntero();

	cout << "Hora: "; hora = leerEntero();

	cout << "Minutos: "; minuto = leerEntero();

	cout << "\nConfirma?. [1: SI || 0: No]:";

	opcion = leerEntero();

	if(opcion == 1)
	{
		Fecha *fecha = new Fecha(dia,mes,anio,hora,minuto);

		controller->setFechaSys(fecha);

		// Limpio la memoria
		delete fecha;
	}

	return CONTINUAR;
}

int ingresarDatosPrueba()
{
    IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    cout << "\nCargando Juego de Datos ... \n";

    controller->ingresarDatosPrueba();

    cout << "\nCarga de Datos Completa. \n\n";

    getchar();

	getchar();

    return CONTINUAR;
}

int mostrarListadoUsuarios()
{
    IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<UsuarioDT*> *usuariosCol = controller->mostrarListadoUsuarios();

    cout << "\nUsuarios: \n\n" << usuariosCol->toString();

    delete usuariosCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoTemas()
{
    IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<TemaDT*> *temasCol = controller->mostrarListadoTemas();

    cout << "\nTemas: \n\n" << temasCol->toString();

    delete temasCol;

    getchar();

	getchar();

	return CONTINUAR;
}
int mostrarListadoSingles()
{
    IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<TemaDT*> *temasCol = controller->mostrarListadoSingles();

    cout << "\nSingles: \n\n" << temasCol->toString();

    delete temasCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoPistas()
{
    IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<TemaDT*> *temasCol = controller->mostrarListadoPistas();

    cout << "\nPistas: \n\n" << temasCol->toString();

    delete temasCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoAlbums()
{
    IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<AlbumDT*> *albumsCol = controller->mostrarListadoAlbums();

    cout << "\nAlbums: \n\n" << albumsCol->toString();

    delete albumsCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoArtistas()
{
	IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<ArtistaDT*> *artistasCol = controller->mostrarListadoArtistas();

    cout << "\nArtistas: \n\n" << artistasCol->toString();

    delete artistasCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoSolistas()
{
   IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<ArtistaDT*> *artistasCol = controller->mostrarListadoSolistas();

    cout << "\nSolistas: \n\n" << artistasCol->toString();

    delete artistasCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoBandas()
{
   IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<ArtistaDT*> *artistasCol = controller->mostrarListadoBandas();

    cout << "\nBandas: \n\n" << artistasCol->toString();

    delete artistasCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoEtiquetas()
{
   IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<EtiquetaDT*> *etiquetasCol = controller->mostrarListadoEtiquetas();

    cout << "\nEtiquetas: \n\n" << etiquetasCol->toString();

    delete etiquetasCol;

    getchar();

	getchar();

	return CONTINUAR;
}

int mostrarListadoReproducciones()
{
   IGlobal *controller = ControllerFactory::getInstance()->getGlobalController();

    ColConcrete<ReproduccionDT*> *reproduccionesCol = controller->mostrarListadoReproducciones();

    cout << "\nReproducciones: \n\n" << reproduccionesCol->toString();

    delete reproduccionesCol;

    getchar();

	getchar();

	return CONTINUAR;
}
